#ifndef SCENE_H
#define SCENE_H

#include <QObject>
#include <vector>
//#include <iostream>

#include "src/scene/camera.h"
#include "src/scene/object.h"
#include "src/scene/light.h"
#include "src/scene/color.h"
#include "src/scene/hbb/tree.h"

#include "src/math/trio.h"

class Render;
class Raytracing;
class PhotonMapping;


class Scene : public QObject{
	Q_OBJECT

    public:
        Scene(Camera * = NULL);
        ~Scene();

        void setBackgroundColor(const Color &_b){backgroundColor = _b; glClearColor(backgroundColor.red,backgroundColor.green,backgroundColor.blue, 1.0);};
        void setBackgroundColorR(double _r){backgroundColor.red = _r;};
        void setBackgroundColorG(double _g){backgroundColor.green = _g;};
        void setBackgroundColorB(double _b){backgroundColor.blue = _b;};
        const Color &getBackgroundColor() const {return backgroundColor;};

        Raytracing *getRaytracing();
        PhotonMapping *getPhotonMapping();
        HBBTree *getTree(){return tree;};
        Camera *getCamera(){return camera;};
        void setObjectsAndLights(const std::vector<Object *> &_objs, const std::vector<Light *> &_ls){objects = _objs; lights = _ls;};
        void setLights(const std::vector<Light *> &_ls){lights = _ls;};
        void addLight(Light *);
        void deleteLight(Light *);
        Light *getLight(unsigned int _i) const {return lights[_i];};
        const std::vector<Light *> &getLights() const {return lights;};
        unsigned int getLightsSize() const {return lights.size();};
        void addObject(Object *_o) {objects.push_back(_o);};
        Object *getObject(unsigned int _i) const {return objects[_i];};
        const std::vector<Object *> &getObjects() const {return objects;};
        unsigned int getObjectsSize() const {return objects.size();};
        void deleteObject(Object *);
        int nextObjectsID() {return idObjects++;};
        void setNextObjectsID(int _id) {idObjects = _id + 1;};
        int nextLightsID() {return idLights++;};
//        void setNextLightsID(int _id) {idLights = _id + 1;};

        void draw(bool, bool, bool, bool = false);

        void doHBBTree();
        void doEmitPhotons(bool = false);
        void doRaytracing();
        void doPhotonMapping(bool = false);
        void testRaytracing(const Ray &);
        void clearTestRay(){listOfPoints.clear();};
        void clearTree(){delete tree; tree = NULL;};
        void clearPhotonsMaps();

        double getEmitPhotonsTime() const {return emitPhotonsTime;};
        double getPhotonMappingPhotonsOnlyTime() const {return photonMappingPhotonsOnlyTime;};
        double getPhotonMappingTime() const {return photonMappingTime;};
        double getRaytracingTime() const {return raytracingTime;};
        double getTreeTime() const {return treeTime;};


    private:
        HBBTree *tree;
        Raytracing *raytracing;
        PhotonMapping *photonMapping;

        Camera *camera;
        std::vector<Light *> lights;//precisa ter pelo menso um ambient light
        std::vector<Object *> objects;
        std::vector<Trio> listOfPoints;
        double treeTime;
        double raytracingTime;
        double photonMappingTime;
        double photonMappingPhotonsOnlyTime;
        double emitPhotonsTime;

        int idObjects;
        int idLights;
        /*configurações */
        Color backgroundColor;

        void drawRay();
        void doRender(Render *, bool = false);

    signals:
        void setLine(unsigned int, uchar *);
};

void transformSecondToTime(int *, int *, int *, int *, double);

#endif
